<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.14.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>DM-CtrlH7-BF-DevProgram: bsp_usart</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<script type="text/javascript" src="clipboard.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript" src="cookie.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectlogo"><img alt="Logo" src="DMBF-Black.png"/></td>
  <td id="projectalign">
   <div id="projectname">DM-CtrlH7-BF-DevProgram<span id="projectnumber">&#160;beta 0.1</span>
   </div>
   <div id="projectbrief">C.ONE Studio Damiao Development Board Framework</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.14.0 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search/",'.html');
</script>
<script type="text/javascript">
$(function() { codefold.init(); });
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('',true,false,'search.php','Search',true);
  $(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(function(){initNavTree('md_bsp_2usart_2bsp__usart.html','',''); });
</script>
<div id="container">
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>

<div><div class="header">
  <div class="headertitle"><div class="title">bsp_usart </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="anchor" id="autotoc_md20"></a></p>
<p align="right"></p>
<p><a href="#" onclick="location.href='mai'+'lto:'+'neo'+'zn'+'g1@'+'hn'+'u.e'+'du'+'.cn'; return false;">neozn<span class="obfuscator">.nosp@m.</span>g1@h<span class="obfuscator">.nosp@m.</span>nu.ed<span class="obfuscator">.nosp@m.</span>u.cn</a></p>
<blockquote class="doxtable">
<p>TODO: 增加发送队列以解决短时间内调用<span class="tt"><a class="el" href="bsp__usart_8c.html#a12acc10fbb458df894b53534ae66c25d" title="通过调用该函数可以发送一帧数据,需要传入一个usart实例,发送buff以及这一帧的长度">USARTSend()</a></span>发生丢包的问题,目前仅支持DMA。还需要提供阻塞和IT模式以供选择，参考bspiic和spi进行实现。 可以直接在发送函数的参数列表添加发送模式选择,或增加instance成员变量,并提供设置模式接口,两者各有优劣 </p>
</blockquote>
<h1 class="doxsection"><a class="anchor" id="autotoc_md21"></a>
使用说明</h1>
<p>若你需要构建新的基于串口的module，首先需要拥有一个<span class="tt">usart_instance</span>的指针用于操作串口对象。</p>
<p>需要在串口实例下设定接收的数据包的长度，实例对应的串口硬件（通过<span class="tt"><a class="el" href="group___u_a_r_t___exported___types.html#ga5de4a49eb132735325e706f406c69d6e" title="UART handle Structure definition.">UART_HandleTypeDef</a></span>指定，如<span class="tt">&amp;huart1</span>），解析接收数据对应的回调函数这三个参数。然后，调用<span class="tt"><a class="el" href="bsp__usart_8c.html#a4296c218240b51944ecb698eed2625ef" title="注册一个串口实例,返回一个串口实例指针">USARTRegister()</a></span>并传入配置好的<span class="tt">usart_instance</span>指针即可。</p>
<p>若要发送数据，调用<span class="tt"><a class="el" href="bsp__usart_8c.html#a12acc10fbb458df894b53534ae66c25d" title="通过调用该函数可以发送一帧数据,需要传入一个usart实例,发送buff以及这一帧的长度">USARTSend()</a></span>。注意buffsize务必小于你创建的buff的大小，否则造成指针越界后果未知。</p>
<p>串口硬件收到数据时，会将其存入<span class="tt">usart_instance.recv_buff[]</span>中，当收到完整一包数据，会调用设定的回调函数<span class="tt">module_callback</span>（即你注册时提供的解析函数）。在此函数中，你可以通过<span class="tt">usart_instance.recv_buff[]</span>访问串口收到的数据。</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md22"></a>
代码结构</h1>
<p>.h文件内包括了外部接口和类型定义,以及模块对应的宏。c文件内为私有函数和外部接口的定义。</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md23"></a>
类型定义</h1>
<div class="fragment"><div class="line"><span class="preprocessor">#define DEVICE_USART_CNT 3     </span><span class="comment">// C板至多分配3个串口</span></div>
<div class="line"><span class="preprocessor">#define USART_RXBUFF_LIMIT 128 </span><span class="comment">// if your protocol needs bigger buff, modify here</span></div>
<div class="line"> </div>
<div class="line"><span class="keyword">typedef</span> void (*usart_module_callback)();</div>
<div class="line"> </div>
<div class="line"><span class="comment">/* usart_instance struct,each app would have one instance */</span></div>
<div class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span></div>
<div class="line">{</div>
<div class="line">    uint8_t recv_buff[USART_RXBUFF_LIMIT]; <span class="comment">// 预先定义的最大buff大小,如果太小请修改USART_RXBUFF_LIMIT</span></div>
<div class="line">    uint8_t recv_buff_size;                <span class="comment">// 模块接收一包数据的大小</span></div>
<div class="line">    <a class="code hl_typedef" href="group___u_a_r_t___exported___types.html#ga5de4a49eb132735325e706f406c69d6e">UART_HandleTypeDef</a> *usart_handle;      <span class="comment">// 实例对应的usart_handle</span></div>
<div class="line">    usart_module_callback module_callback; <span class="comment">// 解析收到的数据的回调函数</span></div>
<div class="line">} usart_instance;</div>
<div class="ttc" id="agroup___u_a_r_t___exported___types_html_ga5de4a49eb132735325e706f406c69d6e"><div class="ttname"><a href="group___u_a_r_t___exported___types.html#ga5de4a49eb132735325e706f406c69d6e">UART_HandleTypeDef</a></div><div class="ttdeci">struct __UART_HandleTypeDef UART_HandleTypeDef</div><div class="ttdoc">UART handle Structure definition.</div></div>
</div><!-- fragment --><ul>
<li><span class="tt">DEVICE_USART_CNT</span>是开发板上可用的串口数量。</li>
<li><span class="tt">USART_RXBUFF_LIMIT</span>是串口单次接收的数据长度上限，暂时设为128，如果需要更大的buffer容量，修改该值。</li>
<li><span class="tt">usart_module_callback()</span>是模块提供给串口接收中断回调函数使用的协议解析函数指针。对于每个需要串口的模块，需要定义一个这样的函数用于解包数据。</li>
<li>每定义一个<span class="tt">usart_instance</span>，就代表一个串口的**实例**（对象）。一个串口实例内有接收buffer，单个数据包的大小，该串口对应的<span class="tt">HAL handle</span>（代表其使用的串口硬件具体是哪一个）以及用于解包数据的回调函数。</li>
</ul>
<h1 class="doxsection"><a class="anchor" id="autotoc_md24"></a>
外部接口</h1>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> <a class="code hl_function" href="bsp__usart_8c.html#a4296c218240b51944ecb698eed2625ef">USARTRegister</a>(usart_instance *_instance);</div>
<div class="line"><span class="keywordtype">void</span> <a class="code hl_function" href="bsp__usart_8c.html#a12acc10fbb458df894b53534ae66c25d">USARTSend</a>(usart_instance *_instance, uint8_t *send_buf, uint16_t send_size);</div>
<div class="ttc" id="absp__usart_8c_html_a12acc10fbb458df894b53534ae66c25d"><div class="ttname"><a href="bsp__usart_8c.html#a12acc10fbb458df894b53534ae66c25d">USARTSend</a></div><div class="ttdeci">void USARTSend(USARTInstance *_instance, uint8_t *send_buf, uint16_t send_size, USART_TRANSFER_MODE mode)</div><div class="ttdoc">通过调用该函数可以发送一帧数据,需要传入一个usart实例,发送buff以及这一帧的长度</div><div class="ttdef"><b>Definition</b> bsp_usart.c:62</div></div>
<div class="ttc" id="absp__usart_8c_html_a4296c218240b51944ecb698eed2625ef"><div class="ttname"><a href="bsp__usart_8c.html#a4296c218240b51944ecb698eed2625ef">USARTRegister</a></div><div class="ttdeci">USARTInstance * USARTRegister(USART_Init_Config_s *init_config)</div><div class="ttdoc">注册一个串口实例,返回一个串口实例指针</div><div class="ttdef"><b>Definition</b> bsp_usart.c:38</div></div>
</div><!-- fragment --><ul>
<li><p class="startli"><span class="tt">USARTRegister</span>是用于初始化串口对象的接口，module层的模块对象（也应当为一个结构体）内要包含一个<span class="tt">usart_instance</span>。</p>
<p class="startli"><b>在调用该函数之前，需要先对其成员变量<span class="tt">*usart_handle</span>,<span class="tt">module_callback()</span>以及<span class="tt">recv_buff_size</span>进行赋值。</b></p>
</li>
<li><span class="tt"><a class="el" href="bsp__usart_8c.html#a12acc10fbb458df894b53534ae66c25d" title="通过调用该函数可以发送一帧数据,需要传入一个usart实例,发送buff以及这一帧的长度">USARTSend()</a></span>是通过模块通过其拥有的串口对象发送数据的接口，调用时传入的参数为串口实例指针，发送缓存以及此次要发送的数据长度（8-bit*n)。</li>
</ul>
<h1 class="doxsection"><a class="anchor" id="autotoc_md25"></a>
私有函数和变量</h1>
<p>在.c文件内设为static的函数和变量</p>
<div class="fragment"><div class="line"><span class="keyword">static</span> usart_instance *instance[DEVICE_USART_CNT];</div>
</div><!-- fragment --><p>这是bsp层管理所有串口实例的入口。</p>
<div class="fragment"><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code hl_function" href="bsp__usart_8c.html#ac45bba3591501c066f505a46dbae7e2b">USARTServiceInit</a>(usart_instance *_instance)</div>
<div class="line"><span class="keywordtype">void</span> <a class="code hl_function" href="group___u_a_r_t___exported___functions___group2.html#ga925534fb8bf7ca464fd05c982fe4bfa0">HAL_UARTEx_RxEventCallback</a>(<a class="code hl_typedef" href="group___u_a_r_t___exported___types.html#ga5de4a49eb132735325e706f406c69d6e">UART_HandleTypeDef</a> *huart, uint16_t Size)</div>
<div class="line"><span class="keywordtype">void</span> <a class="code hl_function" href="group___u_a_r_t___exported___functions___group2.html#ga0e0456ea96d55db31de947fb3e954f18">HAL_UART_ErrorCallback</a>(<a class="code hl_typedef" href="group___u_a_r_t___exported___types.html#ga5de4a49eb132735325e706f406c69d6e">UART_HandleTypeDef</a> *huart)</div>
<div class="ttc" id="absp__usart_8c_html_ac45bba3591501c066f505a46dbae7e2b"><div class="ttname"><a href="bsp__usart_8c.html#ac45bba3591501c066f505a46dbae7e2b">USARTServiceInit</a></div><div class="ttdeci">void USARTServiceInit(USARTInstance *_instance)</div><div class="ttdoc">启动串口服务,会在每个实例注册之后自动启用接收,当前实现为DMA接收,后续可能添加IT和BLOCKING接收</div><div class="ttdef"><b>Definition</b> bsp_usart.c:29</div></div>
<div class="ttc" id="agroup___u_a_r_t___exported___functions___group2_html_ga0e0456ea96d55db31de947fb3e954f18"><div class="ttname"><a href="group___u_a_r_t___exported___functions___group2.html#ga0e0456ea96d55db31de947fb3e954f18">HAL_UART_ErrorCallback</a></div><div class="ttdeci">void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)</div><div class="ttdoc">当串口发送/接收出现错误时,会调用此函数,此时这个函数要做的就是重新启动接收</div><div class="ttdef"><b>Definition</b> bsp_usart.c:127</div></div>
<div class="ttc" id="agroup___u_a_r_t___exported___functions___group2_html_ga925534fb8bf7ca464fd05c982fe4bfa0"><div class="ttname"><a href="group___u_a_r_t___exported___functions___group2.html#ga925534fb8bf7ca464fd05c982fe4bfa0">HAL_UARTEx_RxEventCallback</a></div><div class="ttdeci">void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)</div><div class="ttdoc">每次dma/idle中断发生时，都会调用此函数.对于每个uart实例会调用对应的回调进行进一步的处理 例如:视觉协议解析/遥控器解析/裁判系统解析</div><div class="ttdef"><b>Definition</b> bsp_usart.c:102</div></div>
</div><!-- fragment --><ul>
<li><span class="tt"><a class="el" href="bsp__usart_8c.html#ac45bba3591501c066f505a46dbae7e2b" title="启动串口服务,会在每个实例注册之后自动启用接收,当前实现为DMA接收,后续可能添加IT和BLOCKING接收">USARTServiceInit()</a></span>会被<span class="tt"><a class="el" href="bsp__usart_8c.html#a4296c218240b51944ecb698eed2625ef" title="注册一个串口实例,返回一个串口实例指针">USARTRegister()</a></span>调用，开启接收中断</li>
<li><span class="tt"><a class="el" href="group___u_a_r_t___exported___functions___group2.html#ga925534fb8bf7ca464fd05c982fe4bfa0" title="每次dma/idle中断发生时，都会调用此函数.对于每个uart实例会调用对应的回调进行进一步的处理 例如:视觉协议解析/遥控器解析/裁判系统解析">HAL_UARTEx_RxEventCallback()</a></span>和<span class="tt"><a class="el" href="group___u_a_r_t___exported___functions___group2.html#ga0e0456ea96d55db31de947fb3e954f18" title="当串口发送/接收出现错误时,会调用此函数,此时这个函数要做的就是重新启动接收">HAL_UART_ErrorCallback()</a></span>都是对HAL的回调函数的重定义（原本的callback是<span class="tt">__week</span>修饰的弱定义），前者在发生**IDLE中断**或**单次DMA传输中断**后会被调用（说明收到了完整的一包数据），随后在里面根据中断来源，调用拥有产生了该中断的模块的协议解析函数进行数据解包；后者在串口传输出错的时候会被调用，重新开启接收。 </li>
</ul>
</div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<div id="page-nav" class="page-nav-panel">
<div id="page-nav-resize-handle"></div>
<div id="page-nav-tree">
<div id="page-nav-contents">
</div><!-- page-nav-contents -->
</div><!-- page-nav-tree -->
</div><!-- page-nav -->
</div><!-- container -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.14.0 </li>
  </ul>
</div>
</body>
</html>
